package com.ztewatch.wearcontacts.service;

import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;

import android.app.Activity;
import android.app.IntentService;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.Groups;
import android.provider.ContactsContract.RawContacts;
import android.text.TextUtils;
import android.util.Log;

import com.ztewatch.wearcontacts.data.ContactData;
import com.ztewatch.wearcontacts.utils.ContactPhotoUtils;

public class WearContactSaveService extends IntentService {
	public static final String EXTRA_ACCOUNT_NAME = "accountName";
	public static final String EXTRA_ACCOUNT_TYPE = "accountType";
	public static final String EXTRA_DATA_SET = "dataSet";
	public static final String ACTION_CREATE_GROUP = "createGroup";
	public static final String ACTION_RENAME_GROUP = "renameGroup";
	public static final String ACTION_DELETE_GROUP = "deleteGroup";
	public static final String ACTION_UPDATE_GROUP = "updateGroup";
	public static final String EXTRA_GROUP_ID = "groupId";
	public static final String EXTRA_GROUP_PHOTO = "groupPhoto";
	public static final String EXTRA_GROUP_LABEL = "groupLabel";
	public static final String EXTRA_RAW_CONTACTS_TO_ADD = "rawContactsToAdd";
	public static final String EXTRA_RAW_CONTACTS_TO_REMOVE = "rawContactsToRemove";
	public static final String ACTION_SET_STARRED = "setStarred";
	public static final String ACTION_DELETE_CONTACT = "delete";
	public static final String EXTRA_CONTACT_URI = "contactUri";
	public static final String EXTRA_STARRED_FLAG = "starred";
	public static final String ACTION_SAVE_CONTACT = "saveContact";
	public static final String EXTRA_UPDATED_PHOTOS = "updatedPhotos";
	public static final String EXTRA_CONTACT_NAME = "contactName";
	public static final String EXTRA_CONTACT_PHONE = "contactPhone";
	public static final String EXTRA_CREATE_GROUP_FALG = "createGroupFlag";
	public static final String EXTRA_CONTACT_GROUP_ID = "contactGroupId";
	public static final String EXTRA_CONTACT_STARRED_ID = "contactStarredId";
	public static final String ACTION_UPDATE_CONTACT = "updateContact";
	public static final String EXTRA_RAW_CONTACT_ID = "contactRawcontactId";
	public static final String EXTRA_CALLBACK_INTENT = "callbackIntent";
	public static final String EXTRA_SAVE_SUCCEEDED = "saveSucceeded";

	private static final String TAG = "WearContactSaveService";

	public interface Listener {
		public void onServiceCompleted(Intent callbackIntent);
	}

	private static final CopyOnWriteArrayList<Listener> sListeners = new CopyOnWriteArrayList<Listener>();

	private Handler mMainHandler;

	public WearContactSaveService() {
		super(TAG);
		mMainHandler = new Handler(Looper.getMainLooper());
	}

	public static void registerListener(Listener listener) {
		if (!(listener instanceof Activity)) {
			throw new ClassCastException("Only activities can be registered to"
					+ " receive callback from "
					+ WearContactSaveService.class.getName());
		}
		sListeners.add(0, listener);
	}

	public static void unregisterListener(Listener listener) {
		sListeners.remove(listener);
	}

	public void deliverCallback(final Intent callbackIntent) {
		mMainHandler.post(new Runnable() {

			@Override
			public void run() {
				deliverCallbackOnUiThread(callbackIntent);
			}
		});
	}

	void deliverCallbackOnUiThread(final Intent callbackIntent) {
		// TODO: this assumes that if there are multiple instances of the same
		// activity registered, the last one registered is the one waiting for
		// the callback. Validity of this assumption needs to be verified.
		for (Listener listener : sListeners) {
			if (callbackIntent.getComponent().equals(
					((Activity) listener).getIntent().getComponent())) {
				listener.onServiceCompleted(callbackIntent);
				return;
			}
		}
	}

	@Override
	protected void onHandleIntent(Intent intent) {
		String action = intent.getAction();
		if (ACTION_CREATE_GROUP.equals(action)) {
			createGroup(intent);
		} else if (ACTION_RENAME_GROUP.equals(action)) {
			renameGroup(intent);
		} else if (ACTION_DELETE_GROUP.equals(action)) {
			deleteGroup(intent);
		} else if (ACTION_UPDATE_GROUP.equals(action)) {
			updateGroup(intent);
		} else if (ACTION_DELETE_CONTACT.equals(action)) {
			deleteContact(intent);
		} else if (ACTION_SET_STARRED.equals(action)) {
			setStarred(intent);
		} else if (ACTION_SAVE_CONTACT.equals(action)) {
			saveContact(intent);
		} else if (ACTION_UPDATE_CONTACT.equals(action)) {
			updateContact(intent);
		}
	}

	// public static Intent createUpdateContactIntent(Context context,
	// long rawcontactid, String name, String phone, long groupid,
	// Uri photoUri) {
	// Intent serviceIntent = new Intent(context, WearContactSaveService.class);
	// serviceIntent.setAction(WearContactSaveService.ACTION_UPDATE_CONTACT);
	// serviceIntent.putExtra(EXTRA_CONTACT_NAME, name);
	// serviceIntent.putExtra(EXTRA_CONTACT_PHONE, phone);
	// serviceIntent.putExtra(EXTRA_RAW_CONTACT_ID, rawcontactid);
	// if (photoUri != null) {
	// serviceIntent.putExtra(EXTRA_UPDATED_PHOTOS, photoUri);
	// }
	// if (groupid != 0) {
	// serviceIntent.putExtra(EXTRA_CONTACT_GROUP_ID, groupid);
	// }
	// return serviceIntent;
	// }

	public static Intent createUpdateContactIntent(Context context,
			ContactData contactData,
			Class<? extends Activity> callbackActivity, String callbackAction) {
		Intent serviceIntent = new Intent(context, WearContactSaveService.class);
		serviceIntent.setAction(WearContactSaveService.ACTION_UPDATE_CONTACT);
		serviceIntent.putExtra(EXTRA_CONTACT_NAME, contactData.getName());
		serviceIntent.putExtra(EXTRA_CONTACT_PHONE, contactData.getPhone());
		serviceIntent.putExtra(EXTRA_RAW_CONTACT_ID,
				contactData.getRaw_contact_id());
		if (contactData.getPhoto() != null) {
			serviceIntent
					.putExtra(EXTRA_UPDATED_PHOTOS, contactData.getPhoto());
		}
		if (contactData.getGroup_id() != 0) {
			serviceIntent.putExtra(EXTRA_CONTACT_GROUP_ID,
					contactData.getGroup_id());
		}
		serviceIntent.putExtra(EXTRA_CREATE_GROUP_FALG,
				contactData.isCreateGroup_flag());
		serviceIntent.putExtra(EXTRA_GROUP_LABEL, contactData.getGroup_title());
		if (callbackActivity != null) {
			Intent callbackIntent = new Intent(context, callbackActivity);
			callbackIntent.setAction(callbackAction);
			serviceIntent.putExtra(
					WearContactSaveService.EXTRA_CALLBACK_INTENT,
					callbackIntent);
		}
		return serviceIntent;
	}

	private void updateContact(Intent intent) {
		String name = intent.getStringExtra(EXTRA_CONTACT_NAME);
		String phone = intent.getStringExtra(EXTRA_CONTACT_PHONE);
		// Uri photoUri = intent.getParcelableExtra(EXTRA_UPDATED_PHOTOS);
		byte[] photo = intent.getByteArrayExtra(EXTRA_UPDATED_PHOTOS);
		long groupid = intent.getLongExtra(EXTRA_CONTACT_GROUP_ID, 0);
		long rowContact_id = intent.getLongExtra(EXTRA_RAW_CONTACT_ID, 0);
		boolean create_group_flag = intent.getBooleanExtra(
				EXTRA_CREATE_GROUP_FALG, false);
		String group_title = intent.getStringExtra(EXTRA_GROUP_LABEL);
		boolean succeeded = false;
		if (groupid == 0 && create_group_flag) {
			ContentValues values = new ContentValues();
			values.put(Groups.TITLE, group_title);
			values.put(Groups.GROUP_VISIBLE, 1);
			// Create the new group
			final Uri groupUri = getContentResolver().insert(
					Groups.CONTENT_URI, values);
			groupid = ContentUris.parseId(groupUri);
		}
		// delete this contact group
		try {
			deleteGroupWithRawContactId(rowContact_id);
		} catch (Exception e) {
			e.printStackTrace();
		}

		ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
		// update phone number
		ops.add(ContentProviderOperation
				.newUpdate(ContactsContract.Data.CONTENT_URI)
				.withSelection(
						Data.RAW_CONTACT_ID + "=?" + " AND "
								+ ContactsContract.Data.MIMETYPE + "=?"
								+ " AND " + Phone.TYPE + "=?",
						new String[] { String.valueOf(rowContact_id),
								Phone.CONTENT_ITEM_TYPE,
								String.valueOf(Phone.TYPE_MOBILE) })
				.withValue(Phone.NUMBER, phone).build());

		// update name

		ops.add(ContentProviderOperation
				.newUpdate(ContactsContract.Data.CONTENT_URI)
				.withSelection(
						Data.RAW_CONTACT_ID + "=?" + " AND "
								+ ContactsContract.Data.MIMETYPE + "=?",
						new String[] { String.valueOf(rowContact_id),
								StructuredName.CONTENT_ITEM_TYPE })
				.withValue(StructuredName.DISPLAY_NAME, name).build());
		// add group
		if (groupid != 0) {
			final ContentProviderOperation.Builder insertBuilder = ContentProviderOperation
					.newInsert(Data.CONTENT_URI);
			insertBuilder.withValue(Data.RAW_CONTACT_ID, rowContact_id);
			insertBuilder.withValue(Data.MIMETYPE,
					GroupMembership.CONTENT_ITEM_TYPE);
			insertBuilder.withValue(GroupMembership.GROUP_ROW_ID, groupid);
			ops.add(insertBuilder.build());
		}
		// else{
		// final ContentProviderOperation.Builder deleteBuilder =
		// ContentProviderOperation.newDelete(Data.CONTENT_URI);
		// deleteBuilder.withValue(Data.RAW_CONTACT_ID, rowContact_id);
		// deleteBuilder.withValue(Data.MIMETYPE,
		// GroupMembership.CONTENT_ITEM_TYPE);
		// deleteBuilder.withValue(GroupMembership.GROUP_ROW_ID, groupid);
		// ops.add(deleteBuilder.build());
		// }
		try {
			getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);

			// if (photoUri != null) {
			// saveUpdatedPhoto(rowContact_id, photoUri);
			// }
			if (photo != null) {
				// update photo
				ContentValues values = new ContentValues();
				values.put(ContactsContract.CommonDataKinds.Photo.PHOTO, photo);
				int isUpdate = getContentResolver()
						.update(ContactsContract.Data.CONTENT_URI,
								values,
								Data.RAW_CONTACT_ID + "=?" + " AND "
										+ ContactsContract.Data.MIMETYPE + "=?",
								new String[] {
										String.valueOf(rowContact_id),
										ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE });
				if (isUpdate == 0) {
					values.put(
							ContactsContract.Data.MIMETYPE,
							ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
					values.put(Data.RAW_CONTACT_ID, rowContact_id);
					getContentResolver().insert(
							ContactsContract.Data.CONTENT_URI, values);
				}
			}
			succeeded = true;
			Intent callbackIntent = intent
					.getParcelableExtra(EXTRA_CALLBACK_INTENT);
			if (callbackIntent != null) {
				if (succeeded) {
					// Mark the intent to indicate that the save was successful
					// (even if the lookup URI
					// is now null). For local contacts or the local profile,
					// it's possible that the
					// save triggered removal of the contact, so no lookup URI
					// would exist..
					callbackIntent.putExtra(EXTRA_SAVE_SUCCEEDED, true);
				}
				// callbackIntent.setData(mLookupUri);
				// callbackIntent.putExtra(SAVE_CONTACT_RESULT, result);

				deliverCallback(callbackIntent);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private void deleteGroupWithRawContactId(long rowContact_id) {
		Cursor c = getContentResolver().query(
				ContactsContract.Data.CONTENT_URI, null,
				Data.RAW_CONTACT_ID + "=" + rowContact_id, null, null);
		if (c != null) {
			c.moveToPosition(-1);
			while (c.moveToNext()) {
				int mimetype_index = c.getColumnIndex(Data.MIMETYPE);
				String mimeType = c.getString(mimetype_index);
				if (GroupMembership.CONTENT_ITEM_TYPE.equals(mimeType)) {
					int data1_index = c.getColumnIndex(Data.DATA1);
					String group_id = c.getString(data1_index);
					long id = Long.valueOf(group_id);
					getContentResolver().delete(
							Data.CONTENT_URI,
							Data.RAW_CONTACT_ID + "=? AND " + Data.MIMETYPE
									+ "=? AND " + GroupMembership.GROUP_ROW_ID
									+ "=?",
							new String[] { String.valueOf(rowContact_id),
									GroupMembership.CONTENT_ITEM_TYPE,
									String.valueOf(id) });
					break;
				}
			}
		}
	}

	// public static Intent createSaveContactIntent(Context context, String
	// name,
	// String phone, long groupid, int starredid, Uri photoUri) {
	// Intent serviceIntent = new Intent(context, WearContactSaveService.class);
	// serviceIntent.setAction(WearContactSaveService.ACTION_SAVE_CONTACT);
	// serviceIntent.putExtra(EXTRA_CONTACT_NAME, name);
	// serviceIntent.putExtra(EXTRA_CONTACT_PHONE, phone);
	// if (photoUri != null) {
	// serviceIntent.putExtra(EXTRA_UPDATED_PHOTOS, photoUri);
	// }
	// if (groupid != 0) {
	// serviceIntent.putExtra(EXTRA_CONTACT_GROUP_ID, groupid);
	// }
	// if (starredid != 0) {
	// serviceIntent.putExtra(EXTRA_CONTACT_STARRED_ID, starredid);
	// }
	// return serviceIntent;
	// }

	public static Intent createSaveContactIntent(Context context,
			ContactData contactData,
			Class<? extends Activity> callbackActivity, String callbackAction) {
		Intent serviceIntent = new Intent(context, WearContactSaveService.class);
		serviceIntent.setAction(WearContactSaveService.ACTION_SAVE_CONTACT);
		serviceIntent.putExtra(EXTRA_CONTACT_NAME, contactData.getName());
		serviceIntent.putExtra(EXTRA_CONTACT_PHONE, contactData.getPhone());
		if (contactData.getPhoto() != null) {
			serviceIntent
					.putExtra(EXTRA_UPDATED_PHOTOS, contactData.getPhoto());
		}
		if (contactData.getGroup_id() != 0) {
			serviceIntent.putExtra(EXTRA_CONTACT_GROUP_ID,
					contactData.getGroup_id());
		}
		if (contactData.getStarred_id() != 0) {
			serviceIntent.putExtra(EXTRA_CONTACT_STARRED_ID,
					contactData.getStarred_id());
		}
		serviceIntent.putExtra(EXTRA_CREATE_GROUP_FALG,
				contactData.isCreateGroup_flag());
		serviceIntent.putExtra(EXTRA_GROUP_LABEL, contactData.getGroup_title());
		if (callbackActivity != null) {
			Intent callbackIntent = new Intent(context, callbackActivity);
			callbackIntent.setAction(callbackAction);
			serviceIntent.putExtra(
					WearContactSaveService.EXTRA_CALLBACK_INTENT,
					callbackIntent);
		}
		return serviceIntent;
	}

	private long getInsertedRawContactId(
			final ArrayList<ContentProviderOperation> diff,
			final ContentProviderResult[] results) {
		final int diffSize = diff.size();
		for (int i = 0; i < diffSize; i++) {
			ContentProviderOperation operation = diff.get(i);
			if (operation.getUri().getEncodedPath()
					.contains(RawContacts.CONTENT_URI.getEncodedPath())) {
				return ContentUris.parseId(results[i].uri);
			}
		}
		return -1;
	}

	private void saveContact(Intent intent) {
		String name = intent.getStringExtra(EXTRA_CONTACT_NAME);
		String phone = intent.getStringExtra(EXTRA_CONTACT_PHONE);
		// Uri photoUri = intent.getParcelableExtra(EXTRA_UPDATED_PHOTOS);
		byte[] photo = intent.getByteArrayExtra(EXTRA_UPDATED_PHOTOS);
		long groupid = intent.getLongExtra(EXTRA_CONTACT_GROUP_ID, 0);
		int starredid = intent.getIntExtra(EXTRA_CONTACT_STARRED_ID, 0);
		boolean create_group_flag = intent.getBooleanExtra(
				EXTRA_CREATE_GROUP_FALG, false);
		String group_title = intent.getStringExtra(EXTRA_GROUP_LABEL);
		if (groupid == 0 && create_group_flag) {
			ContentValues values = new ContentValues();
			values.put(Groups.TITLE, group_title);
			values.put(Groups.GROUP_VISIBLE, 1);
			// Create the new group
			final Uri groupUri = getContentResolver().insert(
					Groups.CONTENT_URI, values);
			groupid = ContentUris.parseId(groupUri);
		}
		boolean succeeded = false;

		ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
		ops.add(ContentProviderOperation
				.newInsert(ContactsContract.RawContacts.CONTENT_URI)
				.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
				// .withValue(ContactsContract.RawContacts._ID, 0)
				.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null)
				.withValue(ContactsContract.RawContacts.AGGREGATION_MODE,
						ContactsContract.RawContacts.AGGREGATION_MODE_DISABLED)
				.build());
		// add name
		if (!TextUtils.isEmpty(name)) {
			ops.add(ContentProviderOperation
					.newInsert(ContactsContract.Data.CONTENT_URI)
					.withValueBackReference(
							ContactsContract.Data.RAW_CONTACT_ID, 0)
					.withValue(
							ContactsContract.Data.MIMETYPE,
							ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
					.withValue(
							ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
							name).build());
		}
		// add phone
		if (!TextUtils.isEmpty(phone)) {
			ops.add(ContentProviderOperation
					.newInsert(ContactsContract.Data.CONTENT_URI)
					.withValueBackReference(
							ContactsContract.Data.RAW_CONTACT_ID, 0)
					.withValue(
							ContactsContract.Data.MIMETYPE,
							ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
					.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER,
							phone)
					.withValue(ContactsContract.CommonDataKinds.Phone.TYPE,
							Phone.TYPE_MOBILE).build());
		}
		// add photo

		ops.add(ContentProviderOperation
				.newInsert(ContactsContract.Data.CONTENT_URI)
				.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
				.withValue(
						ContactsContract.Data.MIMETYPE,
						ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
				.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, photo)
				.build());
		// add group
		if (groupid != 0) {
			ops.add(ContentProviderOperation
					.newInsert(ContactsContract.Data.CONTENT_URI)
					.withValueBackReference(
							ContactsContract.Data.RAW_CONTACT_ID, 0)
					.withValue(ContactsContract.Data.MIMETYPE,
							GroupMembership.CONTENT_ITEM_TYPE)
					.withValue(GroupMembership.GROUP_ROW_ID, groupid).build());
		}

		try {
			ContentProviderResult[] results = getContentResolver().applyBatch(
					ContactsContract.AUTHORITY, ops);
			final long rawContactId = getInsertedRawContactId(ops, results);
			Uri mLookupUri = null;
			final Uri rawContactUri = ContentUris.withAppendedId(
					RawContacts.CONTENT_URI, rawContactId);
			mLookupUri = RawContacts.getContactLookupUri(getContentResolver(),
					rawContactUri);
			if (starredid != 0) {
				if (mLookupUri != null) {
					final ContentValues values = new ContentValues(1);
					values.put(Contacts.STARRED, starredid);
					getContentResolver().update(mLookupUri, values, null, null);
				}
			}
			succeeded = true;
			Intent callbackIntent = intent
					.getParcelableExtra(EXTRA_CALLBACK_INTENT);
			if (callbackIntent != null) {
				if (succeeded) {
					// Mark the intent to indicate that the save was successful
					// (even if the lookup URI
					// is now null). For local contacts or the local profile,
					// it's possible that the
					// save triggered removal of the contact, so no lookup URI
					// would exist..
					callbackIntent.putExtra(EXTRA_SAVE_SUCCEEDED, true);
				}
				callbackIntent.setData(mLookupUri);
				// callbackIntent.putExtra(SAVE_CONTACT_RESULT, result);

				deliverCallback(callbackIntent);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private boolean saveUpdatedPhoto(long rawContactId, Uri photoUri) {
		final Uri outputUri = Uri.withAppendedPath(ContentUris.withAppendedId(
				RawContacts.CONTENT_URI, rawContactId),
				RawContacts.DisplayPhoto.CONTENT_DIRECTORY);

		return ContactPhotoUtils.savePhotoFromUriToUri(this, photoUri,
				outputUri, true);
	}

	public static Intent createNewGroupIntent(Context context, String label,
			long[] rawContactsToAdd, byte[] photo,
			Class<? extends Activity> callbackActivity, String callbackAction) {
		Intent serviceIntent = new Intent(context, WearContactSaveService.class);
		serviceIntent.setAction(WearContactSaveService.ACTION_CREATE_GROUP);
		serviceIntent.putExtra(WearContactSaveService.EXTRA_GROUP_LABEL, label);
		serviceIntent.putExtra(
				WearContactSaveService.EXTRA_RAW_CONTACTS_TO_ADD,
				rawContactsToAdd);
		serviceIntent.putExtra(EXTRA_GROUP_PHOTO, photo);
		if (callbackActivity != null) {
			Intent callbackIntent = new Intent(context, callbackActivity);
			callbackIntent.setAction(callbackAction);
			serviceIntent.putExtra(
					WearContactSaveService.EXTRA_CALLBACK_INTENT,
					callbackIntent);
		}
		return serviceIntent;
	}

	private void createGroup(Intent intent) {
		String accountType = intent.getStringExtra(EXTRA_ACCOUNT_TYPE);
		String accountName = intent.getStringExtra(EXTRA_ACCOUNT_NAME);
		String dataSet = intent.getStringExtra(EXTRA_DATA_SET);
		String label = intent.getStringExtra(EXTRA_GROUP_LABEL);
		final long[] rawContactsToAdd = intent
				.getLongArrayExtra(EXTRA_RAW_CONTACTS_TO_ADD);
//		byte[] photo = intent.getByteArrayExtra(EXTRA_GROUP_PHOTO);

		ContentValues values = new ContentValues();
		values.put(Groups.ACCOUNT_TYPE, accountType);
		values.put(Groups.ACCOUNT_NAME, accountName);
		values.put(Groups.DATA_SET, dataSet);
		values.put(Groups.TITLE, label);
		values.put(Groups.GROUP_VISIBLE, 1);
//		if (photo != null) {
//			values.put(GroupListLoaderUtil.GROUP_PHOTO_DATA, photo);
//		}
		final ContentResolver resolver = getContentResolver();

		// Create the new group
		final Uri groupUri = resolver.insert(Groups.CONTENT_URI, values);

		// If there's no URI, then the insertion failed. Abort early because
		// group members can't be
		// added if the group doesn't exist
		if (groupUri == null) {
			Log.e(TAG, "Couldn't create group with label " + label);
			return;
		}

		// Add new group members
		addMembersToGroup(resolver, rawContactsToAdd,
				ContentUris.parseId(groupUri));

		Intent callbackIntent = intent
				.getParcelableExtra(EXTRA_CALLBACK_INTENT);
		if (callbackIntent != null) {
			deliverCallback(callbackIntent);
		}
	}

	/**
	 * Creates an intent that can be sent to this service to rename a group.
	 */
	public static Intent createGroupRenameIntent(Context context, long groupId,
			String newLabel) {
		Intent serviceIntent = new Intent(context, WearContactSaveService.class);
		serviceIntent.setAction(WearContactSaveService.ACTION_RENAME_GROUP);
		serviceIntent.putExtra(WearContactSaveService.EXTRA_GROUP_ID, groupId);
		serviceIntent.putExtra(WearContactSaveService.EXTRA_GROUP_LABEL,
				newLabel);

		return serviceIntent;
	}

	private void renameGroup(Intent intent) {
		long groupId = intent.getLongExtra(EXTRA_GROUP_ID, -1);
		String label = intent.getStringExtra(EXTRA_GROUP_LABEL);

		if (groupId == -1) {
			Log.e(TAG, "Invalid arguments for renameGroup request");
			return;
		}

		ContentValues values = new ContentValues();
		values.put(Groups.TITLE, label);
		final Uri groupUri = ContentUris.withAppendedId(Groups.CONTENT_URI,
				groupId);
		getContentResolver().update(groupUri, values, null, null);

	}

	/**
	 * Creates an intent that can be sent to this service to delete a group.
	 */
	public static Intent createGroupDeletionIntent(Context context,
			long groupId, Class<? extends Activity> callbackActivity,
			String callbackAction) {
		Intent serviceIntent = new Intent(context, WearContactSaveService.class);
		serviceIntent.setAction(WearContactSaveService.ACTION_DELETE_GROUP);
		serviceIntent.putExtra(WearContactSaveService.EXTRA_GROUP_ID, groupId);
		if (callbackActivity != null) {
			Intent callbackIntent = new Intent(context, callbackActivity);
			callbackIntent.setAction(callbackAction);
			serviceIntent.putExtra(
					WearContactSaveService.EXTRA_CALLBACK_INTENT,
					callbackIntent);
		}
		return serviceIntent;
	}

	private void deleteGroup(Intent intent) {
		long groupId = intent.getLongExtra(EXTRA_GROUP_ID, -1);
		if (groupId == -1) {
			Log.e(TAG, "Invalid arguments for deleteGroup request");
			return;
		}

		getContentResolver().delete(
				ContentUris.withAppendedId(Groups.CONTENT_URI, groupId), null,
				null);
	}

	public static Intent createGroupUpdateIntent(Context context, long groupId,
			String newLabel, long[] rawContactsToAdd,
			long[] rawContactsToRemove, byte[] photo,
			Class<? extends Activity> callbackActivity, String callbackAction) {
		Intent serviceIntent = new Intent(context, WearContactSaveService.class);
		serviceIntent.setAction(WearContactSaveService.ACTION_UPDATE_GROUP);
		serviceIntent.putExtra(WearContactSaveService.EXTRA_GROUP_ID, groupId);
		serviceIntent.putExtra(WearContactSaveService.EXTRA_GROUP_LABEL,
				newLabel);
		serviceIntent.putExtra(
				WearContactSaveService.EXTRA_RAW_CONTACTS_TO_ADD,
				rawContactsToAdd);
		serviceIntent.putExtra(
				WearContactSaveService.EXTRA_RAW_CONTACTS_TO_REMOVE,
				rawContactsToRemove);
		serviceIntent.putExtra(EXTRA_GROUP_PHOTO, photo);
		if (callbackActivity != null) {
			Intent callbackIntent = new Intent(context, callbackActivity);
			callbackIntent.setAction(callbackAction);
			serviceIntent.putExtra(
					WearContactSaveService.EXTRA_CALLBACK_INTENT,
					callbackIntent);
		}
		return serviceIntent;
	}

	private void updateGroup(Intent intent) {
		long groupId = intent.getLongExtra(EXTRA_GROUP_ID, -1);
		String label = intent.getStringExtra(EXTRA_GROUP_LABEL);
		long[] rawContactsToAdd = intent
				.getLongArrayExtra(EXTRA_RAW_CONTACTS_TO_ADD);
		long[] rawContactsToRemove = intent
				.getLongArrayExtra(EXTRA_RAW_CONTACTS_TO_REMOVE);
		byte[] photo = intent.getByteArrayExtra(EXTRA_GROUP_PHOTO);

		if (groupId == -1) {
			Log.e(TAG, "Invalid arguments for updateGroup request");
			return;
		}

		final ContentResolver resolver = getContentResolver();
		final Uri groupUri = ContentUris.withAppendedId(Groups.CONTENT_URI,
				groupId);

		// Update group name if necessary
		if (label != null) {
			ContentValues values = new ContentValues();
			values.put(Groups.TITLE, label);
			values.put(Groups.GROUP_VISIBLE, 1);
//			if (photo != null) {
//				values.put(GroupListLoaderUtil.GROUP_PHOTO_DATA, photo);
//			}
			// mContactSaveServiceHelper.updateGroupIfNecessary(values,intent);//wuliqing
			// add about support group view 2014-12-26.
			resolver.update(groupUri, values, null, null);
		}

		// Add and remove members if necessary
		addMembersToGroup(resolver, rawContactsToAdd, groupId);
		removeMembersFromGroup(resolver, rawContactsToRemove, groupId);
	}

	private static void addMembersToGroup(ContentResolver resolver,
			long[] rawContactsToAdd, long groupId) {
		if (rawContactsToAdd == null) {
			return;
		}
		for (long rawContactId : rawContactsToAdd) {
			try {
				final ArrayList<ContentProviderOperation> rawContactOperations = new ArrayList<ContentProviderOperation>();

				// Build an assert operation to ensure the contact is not
				// already in the group
				final ContentProviderOperation.Builder assertBuilder = ContentProviderOperation
						.newAssertQuery(Data.CONTENT_URI);
				assertBuilder.withSelection(
						Data.RAW_CONTACT_ID + "=? AND " + Data.MIMETYPE
								+ "=? AND " + GroupMembership.GROUP_ROW_ID
								+ "=?",
						new String[] { String.valueOf(rawContactId),
								GroupMembership.CONTENT_ITEM_TYPE,
								String.valueOf(groupId) });
				assertBuilder.withExpectedCount(0);
				rawContactOperations.add(assertBuilder.build());

				// Build an insert operation to add the contact to the group
				final ContentProviderOperation.Builder insertBuilder = ContentProviderOperation
						.newInsert(Data.CONTENT_URI);
				insertBuilder.withValue(Data.RAW_CONTACT_ID, rawContactId);
				insertBuilder.withValue(Data.MIMETYPE,
						GroupMembership.CONTENT_ITEM_TYPE);
				insertBuilder.withValue(GroupMembership.GROUP_ROW_ID, groupId);
				rawContactOperations.add(insertBuilder.build());

				// Apply batch
				if (!rawContactOperations.isEmpty()) {
					resolver.applyBatch(ContactsContract.AUTHORITY,
							rawContactOperations);
				}
			} catch (RemoteException e) {
				// Something went wrong, bail without success
				Log.e(TAG, "Problem persisting user edits for raw contact ID "
						+ String.valueOf(rawContactId), e);
			} catch (OperationApplicationException e) {
				// The assert could have failed because the contact is already
				// in the group,
				// just continue to the next contact
				Log.w(TAG,
						"Assert failed in adding raw contact ID "
								+ String.valueOf(rawContactId)
								+ ". Already exists in group "
								+ String.valueOf(groupId), e);
			}
		}
	}

	private static void removeMembersFromGroup(ContentResolver resolver,
			long[] rawContactsToRemove, long groupId) {
		if (rawContactsToRemove == null) {
			return;
		}
		for (long rawContactId : rawContactsToRemove) {
			// Apply the delete operation on the data row for the given raw
			// contact's
			// membership in the given group. If no contact matches the provided
			// selection, then
			// nothing will be done. Just continue to the next contact.
			resolver.delete(
					Data.CONTENT_URI,
					Data.RAW_CONTACT_ID + "=? AND " + Data.MIMETYPE + "=? AND "
							+ GroupMembership.GROUP_ROW_ID + "=?",
					new String[] { String.valueOf(rawContactId),
							GroupMembership.CONTENT_ITEM_TYPE,
							String.valueOf(groupId) });
		}
	}

	/**
	 * Creates an intent that can be sent to this service to delete a contact.
	 */
	public static Intent createDeleteContactIntent(Context context,
			Uri contactUri, Class<? extends Activity> callbackActivity,
			String callbackAction) {
		Intent serviceIntent = new Intent(context, WearContactSaveService.class);
		serviceIntent.setAction(WearContactSaveService.ACTION_DELETE_CONTACT);
		serviceIntent.putExtra(WearContactSaveService.EXTRA_CONTACT_URI,
				contactUri);
		if (callbackActivity != null) {
			Intent callbackIntent = new Intent(context, callbackActivity);
			callbackIntent.setAction(callbackAction);
			serviceIntent.putExtra(
					WearContactSaveService.EXTRA_CALLBACK_INTENT,
					callbackIntent);
		}
		return serviceIntent;
	}

	private void deleteContact(Intent intent) {
		Uri contactUri = intent.getParcelableExtra(EXTRA_CONTACT_URI);
		if (contactUri == null) {
			Log.e(TAG, "Invalid arguments for deleteContact request");
			return;
		}

		getContentResolver().delete(contactUri, null, null);
	}

	/**
	 * Creates an intent that can be sent to this service to star or un-star a
	 * contact.
	 */
	public static Intent createSetStarredIntent(Context context,
			Uri contactUri, int value) {
		Intent serviceIntent = new Intent(context, WearContactSaveService.class);
		serviceIntent.setAction(WearContactSaveService.ACTION_SET_STARRED);
		serviceIntent.putExtra(WearContactSaveService.EXTRA_CONTACT_URI,
				contactUri);
		serviceIntent
				.putExtra(WearContactSaveService.EXTRA_STARRED_FLAG, value);

		return serviceIntent;
	}

	private void setStarred(Intent intent) {
		Uri contactUri = intent.getParcelableExtra(EXTRA_CONTACT_URI);
		int value = intent.getIntExtra(EXTRA_STARRED_FLAG, 0);
		if (contactUri == null) {
			Log.e(TAG, "Invalid arguments for setStarred request");
			return;
		}

		final ContentValues values = new ContentValues(1);
		values.put(Contacts.STARRED, value);
		getContentResolver().update(contactUri, values, null, null);
	}
}
